package com.promis.okhttp;

import android.content.Context;
import android.os.Handler;
import android.util.Log;

import com.promis.util.JsonUtils;
import com.promis.util.NetworkUtils;
import com.promis.util.ReflectUtils;
import com.promis.util.StringUtils;

import java.io.IOException;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.TimeUnit;

import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.Cookie;
import okhttp3.CookieJar;
import okhttp3.HttpUrl;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;

/**
 * Created by jidanbo on 2018/1/31.
 */

public abstract class HttpUploadClient<T> {
    private Context context;
    private static OkHttpClient client = null;
    private static Handler handler;

    public HttpUploadClient(Context context) {
        this.context = context;

        if (client == null) {
            client = new OkHttpClient.Builder()
                    .cookieJar(new CookieJar() {
                        private final HashMap<String, List<Cookie>> cookieStore = new HashMap<>();

                        @Override
                        public void saveFromResponse(HttpUrl httpUrl, List<Cookie> list) {
                            cookieStore.put(httpUrl.url().getHost(), list);
                        }

                        @Override
                        public List<Cookie> loadForRequest(HttpUrl httpUrl) {
                            List<Cookie> cookies = cookieStore.get(httpUrl.url().getHost());
                            return cookies != null ? cookies : new ArrayList<Cookie>();
                        }
                    })
                    .connectTimeout(10, TimeUnit.SECONDS)
                    .readTimeout(10, TimeUnit.SECONDS)
                    .writeTimeout(30, TimeUnit.SECONDS)
                    .build();
        }

        if (handler == null) handler = new Handler();
    }

    public void postAsyn(String url, HttpFileParams params) {
        RequestBody requestBody = params.getBuilder().build();
        ProgressRequestBody progressRequestBody = new ProgressRequestBody(requestBody, new ProgressRequestListener() {
            @Override
            public void onRequestProgress(long bytesWritten, long contentLength, boolean done) {
                HttpUploadClient.this.onRequestProgress(bytesWritten, contentLength, done);
            }
        });
        enqueue(newRequestBuilder(url).addHeader("ParamType", "form").post(progressRequestBody).build());

    }

    private void enqueue(Request request) {
        if (NetworkUtils.isNetworkConnected(context)) {
            client.newCall(request).enqueue(newCallback());
        } else onNetworkDisconnect();
    }

    private Request.Builder newRequestBuilder(String url) {
        return new Request.Builder().url(url).addHeader("X-Client-Type", "Android").addHeader("AcceptType", "json");
    }

    private Callback newCallback() {
        return new Callback() {

            @Override
            public void onFailure(Call call, final IOException e) {
                handler.post(new Runnable() {
                    @Override
                    public void run() {
                        onError("连接异常，请稍后重试!");
                        onFinish();
                    }
                });
            }

            @Override
            public void onResponse(Call call, final Response response) throws IOException {
                if (response.isSuccessful()) {
                    final String responseBody = response.body().string();
                    handler.post(new Runnable() {
                        @Override
                        public void run() {
                            handleResponse(responseBody);
                            onFinish();
                        }
                    });
                } else {
                    onError("响应异常：" + response.code() + "," + response.message());
                    onFinish();
                }
            }
        };
    }

    private void handleResponse(String responseBody) {
        try {
            Type type = ReflectUtils.getSuperclassTypeParameter(getClass());
            T jsonResult = JsonUtils.fromJson(responseBody, type);
            if (JsonNormal.RESULT_LEVEL_SUCCESS.equals(((JsonNormal) jsonResult).getMsgLevel())) {
                onSuccess(jsonResult);
            } else if(((JsonNormal) jsonResult).isSessionInvaild()) {
                onSeesionInvaild();
            } else {
                onError(((JsonNormal) jsonResult).getMsgContent());
            }
        } catch (Exception ex) {
            //Toast.makeText(getContext(), ex.getMessage(), Toast.LENGTH_LONG).show();
            if (ex != null && !StringUtils.isNullOrEmpty(ex.getMessage())) {
                Log.e("Response Error: ", ex.getMessage());
            }
            onError("响应数据解析异常" + ex.getMessage());
        }
    }

    public Context getContext() {
        return context;
    }

    protected abstract void onSuccess(T result);

    protected void onError(String errorMsg) {}

    protected void onSeesionInvaild() {}

    protected void onFinish(){}

    protected void onNetworkDisconnect(){}

    public void onRequestProgress(long bytesWritten, long contentLength, boolean done) {};
}
